/**
 * 
 */
package cs342.project1.mathNotebook.PKI;

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;


/** Represents a paired set of keys for the RSA asymmetric encryption scheme. Also used to generate new key pairs.
 * @author Aaron Heise
 *
 */
public class SimpleRSAKeyPair {
	protected SimpleRSAPublicKey publicKey = null;
	protected SimpleRSAPrivateKey privateKey = null;
	
	/** Creates a new key pair from a private and public key.  
	 * @param publicKey the Public Key
	 * @param privateKey the Private Key
	 * @throws SimpleRSAKeyMismatchException if keys do not form an RSA key pair mathematically
	 */
	public SimpleRSAKeyPair(SimpleRSAPublicKey publicKey, SimpleRSAPrivateKey privateKey) throws SimpleRSAKeyMismatchException {
		if(SimpleRSAKeyPair.checkKeyPair(publicKey, privateKey)) {
			this.publicKey = publicKey;
			this.privateKey = privateKey;
		} else {
			throw new SimpleRSAKeyMismatchException("Supplied keys do not mathematically pair.");
		}
	}
	
	/** Creates a new pair of RSA keys from random data.
	 * @return new SimpleRSAKeyPair with random key
	 * @throws SimpleRSAAlgorithmException Problem with RSA or SHA1PRNG implementation used by JVM
	 * @throws SimpleRSAKeyMismatchException Generated keys don't match.
	 */
	public static SimpleRSAKeyPair generateKeyPair() throws SimpleRSAKeyMismatchException, SimpleRSAAlgorithmException {
		KeyPairGenerator kpg;
		SecureRandom secureSeed = null;
		try {
			kpg = KeyPairGenerator.getInstance("RSA");
			secureSeed = SecureRandom.getInstance("SHA1PRNG");
		} catch (NoSuchAlgorithmException e) {
			throw new SimpleRSAAlgorithmException("Problem with algorithm initialization.", e);
		}
		secureSeed.setSeed(secureSeed.generateSeed(20));
		kpg.initialize(2048,secureSeed);
		KeyPair kp = kpg.genKeyPair();
		return new SimpleRSAKeyPair(new SimpleRSAPublicKey((RSAPublicKey) kp.getPublic()), 
									new SimpleRSAPrivateKey((RSAPrivateKey) kp.getPrivate()));
	}
	
	/** Checks if publicKey mathematically pairs with privateKey
	 * @return Returns true if publicKey and privateKey form a pair
	 */
	public static boolean checkKeyPair(SimpleRSAPublicKey publicKey, SimpleRSAPrivateKey privateKey) {
		String testStr = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0";
		byte[] encData = publicKey.encrypt(testStr.getBytes());
		byte[] clearData = privateKey.decrypt(encData);
		String clearStr = new String(clearData);
		return testStr.equals(clearStr);
	}
	
	public SimpleRSAPublicKey getPublic() {
		return publicKey;
	}
	
	public SimpleRSAPrivateKey getPrivate() {
		return privateKey;
	}

}
